package com.steak.orm.threadpool;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 刘牌
 * @Title:
 * @date 2022/2/259:56
 */
public class ThreadPoolService {
	//核心线程数设置未CPU核数 * 10 * 2 ， 如8核则核心线程数为10个，因为批量添加消息，属于IO密集型，所以多分配一下线程
	private static final int CORE_POOL_SIZE = (int) (Runtime.getRuntime().availableProcessors() / (1-0.9)) * 2;
	private static final int MAXIMUM_POOL_SIZE = (int) (Runtime.getRuntime().availableProcessors() / (1-0.9)) * 5;
	private static final long KEEP_ALIVE_TIME = 3;
	private static final TimeUnit UNIT = TimeUnit.SECONDS;
	private static final BlockingQueue<Runnable> WORK_QUEUE = new LinkedBlockingQueue<>();
	private static final MyThreadFactory THREAD_FACTORY = new MyThreadFactory("send-msg");
	private static final ThreadPoolExecutor poolExecutor =
		new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, UNIT, WORK_QUEUE, THREAD_FACTORY, new ThreadPoolExecutor.DiscardOldestPolicy());

	public ExecutorService getThreadPool(){
		return poolExecutor;
	}
	/**
	 * 自定义线程工厂
	 *
	 * 线程工厂可以设置线程信息
	 */
	static class MyThreadFactory implements ThreadFactory {
		private final AtomicInteger poolNumber = new AtomicInteger(1);
		private final ThreadGroup group;
		private final AtomicInteger threadNumber = new AtomicInteger(1);
		private final String namePrefix;

		/**
		 * 构造函数传入我们想业务需要的线程名字threadName，方便发生异常是追溯
		 * @param threadName
		 */
		public MyThreadFactory(String threadName) {
			SecurityManager s = System.getSecurityManager();
			group = (s != null) ? s.getThreadGroup() :
				Thread.currentThread().getThreadGroup();
			if (threadName == null || threadName.isEmpty()){
				threadName = "msg-thread";
			}
			namePrefix = threadName +
				poolNumber.getAndIncrement() +
				"-thread-";
		}

		public Thread newThread(Runnable r) {
			Thread t = new Thread(group, r,
				namePrefix + threadNumber.getAndIncrement(),
				0);
			if (t.isDaemon())
				t.setDaemon(false);
			if (t.getPriority() != Thread.NORM_PRIORITY)
				t.setPriority(Thread.NORM_PRIORITY);
			return t;
		}
	}
}
